package czh.cocoa.ui.impl;

import czh.cocoa.foundation.NSMutableArray;
import czh.cocoa.foundation.NSObject;
import czh.cocoa.foundation.NSSelector;
import czh.cocoa.foundation.NSSet;
import czh.cocoa.graphics.CGPoint;
import czh.cocoa.graphics.CGRect;
import czh.cocoa.ui.UIEvent;
import czh.cocoa.ui.UITouch;
import czh.cocoa.ui.UIView;

public class UIControl extends UIView {

	public final static int UIControlStateNormal = 0;
	public final static int UIControlStateHighlighted = 1 << 0;
	public final static int UIControlStateDisabled = 1 << 1;
	public final static int UIControlStateSelected = 1 << 2;
	
	public final static int UIControlEventTouchDown = 1 <<  0;
	public final static int UIControlEventTouchUpInside = 1 <<  6;
	public final static int UIControlEventTouchUpOutside = 1 <<  7;
	public final static int UIControlEventValueChanged = 1 <<  12;
	
	private int mState;
	
	private boolean mTracking;
	
	private NSMutableArray mTargetActions;
	
	public UIControl() {
		
	}
	
	public UIControl(CGRect frame) {
		super(frame);
	}
	
	protected void init() {
		super.init();
		mTargetActions = new NSMutableArray(3);
	}
	
	public void addTargetActionForControlEvents(NSObject target, NSSelector action, int controlEvents) {
		UIControlAction ca = new UIControlAction();
		ca.target = target;
		ca.action = action;
		ca.controlEvents = controlEvents;
		mTargetActions.addObject(ca);
	}
	
	public void removeTargetActionForControlEvents(NSObject target, NSSelector action, int controlEvents) {
		for (NSObject o : mTargetActions) {
			UIControlAction ca = (UIControlAction) o;
			if (ca.action.isEqual(action) && ca.target == target &&
					ca.controlEvents == controlEvents) {
				mTargetActions.removeObject(ca);
				return;
			}
		}
	}
	
	public void sendActionsForControlEvents(int controlEvents) {
		for (NSObject o : mTargetActions) {
			UIControlAction ca = (UIControlAction) o;
			if (ca.controlEvents == controlEvents) {
				sendActionToTargetForEvent(ca.action, ca.target, null);	
			}
		}
	}
	
	public void sendActionToTargetForEvent(NSSelector action, NSObject target, UIEvent event) {
		if (action != null) {
			action.perform(target, this);
		}
	}
	
	public int state() {
		return mState;
	}
	
	private void setState(int state) {
		if (mState != state) {
			int state0 = mState;
			mState = state;
			onStateChanged(state0, state); 
		}
	}
	
	protected void onStateChanged(int oldState, int newState) {
		
	}
	
	public void setEnabled(boolean enabled) {
		if (enabled) {
			setState(mState & ~UIControlStateDisabled);
		} else {
			setState(mState | UIControlStateDisabled);
		}
	}
	
	public boolean isEnabled() {
		return (mState & UIControlStateDisabled) != UIControlStateDisabled;
	}
	
	public void setHighlighted(boolean highlighted) {
		if (highlighted) {
			setState(mState | UIControlStateHighlighted);
		} else {
			setState(mState & ~UIControlStateHighlighted);
		}
	}
	
	public boolean isHighlighted() {
		return (mState & UIControlStateHighlighted) == UIControlStateHighlighted;
	}
	
	public void setSelected(boolean selected) {
		if (selected) {
			setState(mState | UIControlStateSelected);
		} else {
			setState(mState & ~UIControlStateSelected);
		}
	}
	
	public boolean isSelected() {
		return (mState & UIControlStateSelected) == UIControlStateSelected;
	}
	
	public boolean tracking() {
		return mTracking;
	}
	
	public boolean beginTrackingWithTouchWithEvent(UITouch touch, UIEvent event) {
		if (isEnabled()) {
			setHighlighted(true);
			sendActionsForControlEvents(UIControlEventTouchDown);
			return true;
		}
		return false;
	}
	
	public boolean continueTrackingWithTouchWithEvent(UITouch touch, UIEvent event) {
		setHighlighted(true);
		return true;
	}
	
	public void endTrackingWithTouchWithEvent(UITouch touch, UIEvent event) {
		setHighlighted(false);
		
		CGPoint point = touch.locationInView(superview());
		if(pointInsideWithEvent(point, event)) {
			sendActionsForControlEvents(UIControlEventTouchUpInside);
		} else {
			sendActionsForControlEvents(UIControlEventTouchUpOutside);
		}
		
	}
	
	public void cancelTrackingWithEvent(UIEvent event) {
		setHighlighted(false);
	}
	
	public void touchesBeganWithEvent(NSSet touches, UIEvent event) {
		UITouch touch = (UITouch) touches.anyObject();
		mTracking = beginTrackingWithTouchWithEvent(touch, event);
	}
	
	public void touchesMovedWithEvent(NSSet touches, UIEvent event) {
		if (mTracking) {
			UITouch touch = (UITouch) touches.anyObject();
			mTracking = continueTrackingWithTouchWithEvent(touch, event);
		}
	}
	
	public void touchesEndedWithEvent(NSSet touches, UIEvent event) {
		if (mTracking) {
			UITouch touch = (UITouch) touches.anyObject();
			endTrackingWithTouchWithEvent(touch, event);
			mTracking = false;
		}
	}
	
	public void touchesCancelledWithEvent(NSSet touches, UIEvent event) {
		if (mTracking) {
			cancelTrackingWithEvent(event);
			mTracking = false;
		}
	}
	
	private class UIControlAction extends NSObject {
		
		public NSSelector action;
		
		public NSObject target;
		
		public int controlEvents;
		
	}
	
}
